package net.sourceforge.peers.sip.transport;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketTimeoutException;
import java.security.AccessController;
import java.security.PrivilegedAction;

import net.sourceforge.peers.Config;
import net.sourceforge.peers.Logger;
import net.sourceforge.peers.sip.transaction.TransactionManager;

/**
 * 使用DatagramSocket接收消息 基于UDP
 * @author Mr.Yan
 */
public class UdpMessageReceiver extends MessageReceiver {

    private final DatagramSocket datagramSocket;
    
    public UdpMessageReceiver(DatagramSocket datagramSocket,
            TransactionManager transactionManager,
            TransportManager transportManager, Config config,
            Logger logger) {
        super(datagramSocket.getLocalPort(), transactionManager,
                transportManager, config, logger);
        this.datagramSocket = datagramSocket;
    }

    @Override
    protected void listen() throws IOException {
        byte[] buf = new byte[BUFFER_SIZE];
        final DatagramPacket packet = new DatagramPacket(buf, buf.length);
        final int noException = 0;
        final int socketTimeoutException = 1;
        final int ioException = 2;
        int result = AccessController.doPrivileged(
                (PrivilegedAction<Integer>) () -> {
                    try {
                        datagramSocket.receive(packet);
                    } catch (SocketTimeoutException e) {
                        return socketTimeoutException;
                    } catch (IOException e) {
                        logger.error("cannot receive packet", e);
                        return ioException;
                    }
                    return noException;
                });

        switch (result) {
            case socketTimeoutException:
                return;
            case ioException:
                throw new IOException();
            default:
                break;
        }

        //获取接受到的byte数组
        byte[] trimmedPacket = new byte[packet.getLength()];
        System.arraycopy(packet.getData(), 0, trimmedPacket, 0, trimmedPacket.length);
        processMessage(trimmedPacket, packet.getAddress(), packet.getPort());
    }


}
